package com.only4play.practice.invoice.core.domainservice;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.NumberUtil;
import com.only4play.practice.common.enums.ReceiptStatus;
import com.only4play.practice.common.enums.ValidStatus;
import com.only4play.practice.invoice.api.model.OrderRegisterModel;
import com.only4play.practice.invoice.api.model.OrderRegisterResultModel;
import com.only4play.practice.invoice.core.domainservice.IOrderReceiptDomainService;
import com.only4play.practice.invoice.core.domainservice.model.exchange.ExchangeConditionModel;
import com.only4play.practice.invoice.core.domainservice.model.exchange.ExchangeInvoiceModel;
import com.only4play.practice.invoice.core.domainservice.model.exchange.ExchangeInvoiceResultModel;
import com.only4play.practice.invoice.core.domainservice.pipeline.FilterChainPipeline;
import com.only4play.practice.invoice.core.domainservice.pipeline.context.ExchangeInvoiceContext;
import com.only4play.practice.invoice.core.domainservice.pipeline.context.OrderReceiptContext;
import com.only4play.practice.invoice.core.domainservice.pipeline.filters.exchange.InputCheckFilter;
import com.only4play.practice.invoice.core.domainservice.pipeline.filters.exchange.PopulateInvoiceFilter;
import com.only4play.practice.invoice.core.domainservice.pipeline.filters.exchange.SaveExchangeLogFilter;
import com.only4play.practice.invoice.core.domainservice.pipeline.filters.exchange.SplitAmountFilter;
import com.only4play.practice.invoice.core.domainservice.pipeline.filters.register.CalculateValidAmountFilter;
import com.only4play.practice.invoice.core.domainservice.pipeline.filters.register.EnterpriseRouterFilter;
import com.only4play.practice.invoice.core.domainservice.pipeline.filters.register.PopulateReceiptItemFilter;
import com.only4play.practice.invoice.core.domainservice.pipeline.filters.register.SaveRegisterLogFilter;
import com.only4play.practice.invoice.core.entity.OrderReceipt;
import com.only4play.practice.invoice.core.envents.OrderReceiptEvents;
import com.only4play.practice.invoice.core.facade.IFlowNoFacade;
import com.only4play.practice.ordercommon.constants.BizEnum;
import com.only4play.practice.ordercommon.filters.selector.FilterSelector;
import com.only4play.practice.ordercommon.filters.selector.LocalListBasedFilterSelector;
import com.only4play.practice.ordercommon.pay.PayItem;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;

/**
 * @author mdy
 * * @date 2024/9/15
 */
@Service
@RequiredArgsConstructor
public class OrderReceiptDomainServiceImpl implements IOrderReceiptDomainService {

    //
    private final FilterChainPipeline orderRegisterPipeline;

    private final IFlowNoFacade flowNoFacade;

    private final ApplicationEventPublisher publisher;

    private final FilterChainPipeline exchangeInvoicePipeline;


    /**
     * 配置订单注册的filter
     * @return
     */
    private FilterSelector getOrderRegisterSelector() {
        LocalListBasedFilterSelector selector = new LocalListBasedFilterSelector();
        selector.addFilter(CalculateValidAmountFilter.class.getSimpleName());
        selector.addFilter(SaveRegisterLogFilter.class.getSimpleName());
        selector.addFilter(PopulateReceiptItemFilter.class.getSimpleName());
        selector.addFilter(EnterpriseRouterFilter.class.getSimpleName());
        return selector;
    }

    /**
     * 配置开票要加载的filter
     * @return
     */
    private FilterSelector getExchangeSelector() {
        LocalListBasedFilterSelector selector = new LocalListBasedFilterSelector();
        selector.addFilter(SaveExchangeLogFilter.class.getSimpleName());
        selector.addFilter(SplitAmountFilter.class.getSimpleName());
        selector.addFilter(InputCheckFilter.class.getSimpleName());
        selector.addFilter(PopulateInvoiceFilter.class.getSimpleName());
        return selector;
    }

    @Override
    public OrderRegisterResultModel orderRegister(OrderRegisterModel registerModel) {

        //选择要执行的filter
        FilterSelector selector = getOrderRegisterSelector();
        //构建上下文
        OrderReceiptContext orderReceiptContext = new OrderReceiptContext(BizEnum.BIZ_XXX, selector);
        //请求模型设置到上下文
        orderReceiptContext.setModel(registerModel);
        //设置一个结果bean
        OrderRegisterResultModel resultModel = new OrderRegisterResultModel();
        orderReceiptContext.setRegisterResultModel(resultModel);
        // 按照添加的顺序执行filter，这里怎么实现？
        orderRegisterPipeline.getFilterChain().handle(orderReceiptContext);
        //调用凭据对象的注册方法、
        OrderReceipt orderReceipt = new OrderReceipt();
        BeanUtil.copyProperties(registerModel,orderReceipt);
        orderReceipt.setRegisterFlowNo(flowNoFacade.getNextId());

        orderRegister(orderReceipt,registerModel, resultModel);
        return orderReceiptContext.getRegisterResultModel();
    }

    @Override
    public boolean receiptAbandon(List<Long> ids) {
        return false;
    }

    /**
     * 获取票面信息
     * @param exchangeInvoiceModel
     * @return
     */
    @Override
    public ExchangeInvoiceResultModel exchangeInvoice(
            ExchangeInvoiceModel exchangeInvoiceModel) {
        FilterSelector selector = getExchangeSelector();
        ExchangeInvoiceContext invoiceContext = new ExchangeInvoiceContext(BizEnum.BIZ_XXX, selector);
        invoiceContext.setExchangeInvoiceModel(exchangeInvoiceModel);
        ExchangeInvoiceResultModel resultModel = new ExchangeInvoiceResultModel();
        invoiceContext.setResultModel(resultModel);
        exchangeInvoicePipeline.getFilterChain().handle(invoiceContext);
        return invoiceContext.getResultModel();
    }

    @Override
    public ExchangeInvoiceResultModel exchangeInvoiceByCondition(ExchangeConditionModel conditionModel) {
        return null;
    }

    @Override
    public void completeInvoice(List<Long> ids) {

    }


    /**
     * 订单注册为凭据
     *
     * @param registerModel
     * @param resultModel
     */
    public void orderRegister(OrderReceipt orderReceipt,OrderRegisterModel registerModel,
                              OrderRegisterResultModel resultModel) {
        orderReceipt.setValidStatus(ValidStatus.VALID);
        orderReceipt.setReceiptStatus(ReceiptStatus.UNMAKING);
        if (IterUtil.isNotEmpty(resultModel.getValidList())) {
            orderReceipt.setValidList(resultModel.getValidList());
            orderReceipt.setValidAmount(resultModel.getValidList()
                    .stream()
                    .map(PayItem::getMoney)
                    .reduce(BigDecimal.ZERO, NumberUtil::add).longValue());
        } else {
            orderReceipt.setValidList(Collections.emptyList());
            orderReceipt.setValidAmount(0L);
        }
        if (IterUtil.isNotEmpty(resultModel.getInvalidList())) {
            orderReceipt.setInvalidList(resultModel.getInvalidList());
            orderReceipt.setInvalidAmount(resultModel.getInvalidList()
                    .stream()
                    .map(PayItem::getMoney)
                    .reduce(BigDecimal.ZERO, NumberUtil::add).longValue());
        } else {
            orderReceipt.setInvalidList(Collections.emptyList());
            orderReceipt.setInvalidAmount(0L);
        }
        orderReceipt.setTaxCode(resultModel.getTaxCode());
        publisher.publishEvent(new OrderReceiptEvents.OrderRegisterEvent(orderReceipt, registerModel, resultModel));
    }
}
